#!/usr/bin/env python
# -*- coding: utf-8 -*-
# dialogbox.py
#
# Conversations 'n' shit

import pyglet
from pyglet.gl import *

from os import path
import re

faces = { "Tomten": pyglet.resource.image("tomte.png"),
          "Dingo": pyglet.resource.image("dingo.png"),
          }

def load_dialogue(dialogue_file):
    """Read the dialogue from a file and return a list of
    (face_id, text) tuples."""

    ret_list = []
    dialogue_script = pyglet.resource.file(dialogue_file).read()
    
    statements = re.split("STATEMENT\n", dialogue_script)
    for statement in statements:
        if not statement:
            continue
        m = re.search("(?s)FACE (.*?)\nTEXT (.*)\n*", statement)
        face = m.group(1)
        text = m.group(2).replace("\n", " ").decode("utf-8")
        ret_list.append((face, text))
        
    return ret_list

class Dialogue(object):
    """A dialogue is an ordering of statements, or
    collection of sentences, said by one person at a time.
    """
    def __init__(self, dialogue_file):
        self.dialogue = iter(load_dialogue(dialogue_file))
    def get(self):
        """Get the next statement, as a list of (id, message)
        pairs, where id is the id of the person talking and
        message is the things said by that person."""
        return self.dialogue.next()

class DialogueEnd(Exception):
    pass

class DialogBox(object):
    def __init__(self, dialogue, width, height, pos):
        self.height, self.width = height, width
        self.x, self.y = pos[0], pos[1]
        self.setup_boxes()
    
        self.dialogue_label = pyglet.text.HTMLLabel(text="", 
                                                    width=self.width - 200, height=self.height * 0.8,
                                                    multiline=True,
                                                    anchor_x="left", anchor_y="bottom")
                                                    
        self.dialogue = dialogue
        self.message = ""
        self.message_rest = ""
        self.next()

    def update(self, dt):
        """Do animations and crap."""
        pass

    def draw(self):
        glPushMatrix()

        # Draw the text box
        glLoadIdentity()
        glTranslatef(self.x, self.y, 0)
        self.textbox_vlist.draw(GL_QUADS)
        
        # Fill the box for the face
        glLoadIdentity()
        glTranslatef(self.x - 10, self.y + 10, 0)
        self.facebox_vlist.colors = [255, 255, 255,
                                     255, 255, 255,
                                     255, 255, 255,
                                     255, 255, 255]
        self.facebox_vlist.draw(GL_QUADS)
        
        # Draw the face
        image = faces[self.character_id]
        image.blit(0, 0)

        # Draw a border around the box
        self.facebox_vlist.colors = [0, 0, 0,
                                     0, 0, 0,
                                     0, 0, 0,
                                     0, 0, 0]
        glLineWidth(3)
        glEnable(GL_LINE_SMOOTH)
        self.facebox_vlist.draw(GL_LINE_LOOP)

        # Draw the text
        glLoadIdentity()
        glTranslatef(self.x + 100 + 20, self.y, 0)
        self.dialogue_label.draw()

        glPopMatrix()

    def next(self):
        """Get the next statement in the dialogue."""

        if self.message_rest:
            message = self.message_rest
        else:
            try:
                self.character_id, message =  self.dialogue.get()
            except StopIteration:
                raise DialogueEnd

        self.set_message(message)

    def set_message(self, message):
        """Update the dialogue label.
        Split message up into parts that
        will fit inside the dialogbox if 
        it's too long."""

        words = message.split(" ")
        dropped_words = 0

        self.dialogue_label.text = "<font face='SMonohand'>" + message + "</font>"
        while self.dialogue_label.content_height > self.dialogue_label.height:
            dropped_words += 1
            self.dialogue_label.text = "<font face='SMonohand'>" + " ".join(words[:-dropped_words]) + "</font>"

        if dropped_words > 0:
            self.message_rest = " ".join(words[-dropped_words:])
        else:
            self.message_rest = ""

    def setup_boxes(self):
        self.textbox_vlist = pyglet.graphics.vertex_list(4,
                                                         ("v2f/static", (0, 0,
                                                                         0, self.height,
                                                                         self.width, self.height,
                                                                         self.width, 0)),
                                                         ("c3B/static", (255, 255, 255,
                                                                         255, 255, 255,
                                                                         255, 255, 255,
                                                                         0,   100, 255))
                                                         )

        self.facebox_vlist = pyglet.graphics.vertex_list(4,
                                                         ("v2f/static", (0,   0,
                                                                         0,   100,
                                                                         100, 100,
                                                                         100, 0)),
                                                          ("c3B/stream")
                                                          )
def test():
    win_width = 640
    win_height = 480
    
    pyglet.resource.add_font("SMonohand.ttf")

    window = pyglet.window.Window(win_width, win_height)

    diag = Dialogue("howto.diag")
    box = DialogBox(diag, 0.8*win_width, 0.2*win_height, (10, 10))
    
    glClearColor(0, 1, 0, 0)

    @window.event
    def on_draw():
        window.clear()
        box.draw()
    @window.event
    def on_key_press(symbol, modifiers):
        box.next()
    try:
        pyglet.app.run()
    except DialogueEnd:
        print "Exiting."

if __name__ == "__main__":
    test()
    
